package pro.zfb.web;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.xiaoleilu.hutool.json.JSONObject;

import com.yy.kit.collections.YYMapKits;
import com.yy.kit.http.YYRequestKits;
import com.yy.kit.json.YYJSONKits;
import com.yy.kit.log.YYLogKits;
import com.yy.kit.string.YYStrKits;
import com.yy.kit.zfb.constans.AlipayConstants;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import pro.zfb.service.zfb.enter.IZFBEnterService;
import pro.zfb.service.zfb.follow.IZFBFollowService;
import pro.zfb.service.zfb.verifygw.IZFBVerifygwService;

/**
 * <p>
 * 配置支付宝网关及接收用户事件controller
 * </p>
 *
 * @author 杨阳
 * @since 2017年9月28日
 */
@Controller
@Api(tags = {"配置支付宝网关及接收用户事件controller"})
@RequestMapping("/zfb")
public class ZFBController {

    @Resource(name = "iZFBVerifygwService")
    private IZFBVerifygwService iZFBVerifygwService; //验证网关相关服务
    @Resource(name = "iZFBFollowService")
    private IZFBFollowService iZFBFollowService; //关注取消关注服务层
    @Resource(name = "iZFBEnterService")
    private IZFBEnterService iZFBEnterService; //进入事件

    //支付宝响应消息
    private String responseMsg = "";

    /**
     * <p>
     * 接收支付宝生活号事件
     * biz_content内容：
     * <XML>
     * <AppId><![CDATA[2014070100171523]]></AppId>
     * <FromUserId><![CDATA[20882837462837462837462837461234]]></FromUserId>
     * <FromAlipayUserId><![CDATA[2088283746283746]]></FromAlipayUserId>
     * <CreateTime><![CDATA[1405943673657]]></CreateTime>
     * <MsgType><![CDATA[event]]></MsgType>
     * <EventType><![CDATA[follow]]></EventType>
     * <ActionParam><![CDATA[{"scene":{"sceneId": "1234"}}]]></ActionParam>
     * <AgreementId><![CDATA[]]></AgreementId> <AccountNo><![CDATA[]]></AccountNo>
     * <UserInfo><![CDATA[{"logon_id":"135****1009","user_name":"*iuxu527"}]]></UserInfo>
     * </XML>
     * 参数名 					是否必须						参数说明
     * AppId 					是 							服务窗账号ID
     * FromAlipayUserId 		是 							用户userid，用户唯一标识
     * CreateTime 				是 							消息创建时间 MsgType 是 消息类型，事件类消息固定为event EventType 是 follow：关注事件；unfollow：取消关注事件 enter:进入生活号事件 click:菜单点击事件
     * UserInfo 				是							支付宝的用户信息，JSON格式，包含加星的用户账号及加星的用户名 示例：{"logon_id": "135**1009","user_name":"*iuxu527"}
     * </p>
     *
     * @param request {@link HttpServletRequest}
     */
    @RequestMapping(value = "/gateway", method = RequestMethod.POST)
    @ApiOperation(value = "接收支付宝生活号事件 ", tags = {"处理支付请求，并且返回支付宝!"}, httpMethod = "POST")
    public void gateway(HttpServletRequest request, HttpServletResponse response) {
        YYLogKits.info(ZFBController.class, "┌───────────────────────────────────────────────────────────────────────────┐");

        try {
            // 1. 解析请求参数
            Map<String, String> params = YYMapKits.createStringHashMap();
            params = YYRequestKits.getRequestParams(request);
            YYLogKits.info(ZFBController.class, "├支付宝网关内容:{} ", params.toString());

            // 2.获取请求内容信息，XML格式
            String bizContent = params.get("biz_content");
            YYLogKits.info(ZFBController.class, "├xml格式消息内容{}", bizContent);

            // 3. 将xml格式的内容转换为json格式
            JSONObject json = YYJSONKits.parseFromXml(bizContent).getJSONObject("XML");
            YYLogKits.info(ZFBController.class, "├json格式消息内容{}", json.toString());

            // 4.验证签名 TODO 这里正式环境的时候应该打开，因为现在我的号可能是没有签约成功，所以无法验签成功
//			if (!AlipaySignature.rsaCheckV2(params, AlipayConstants.ALIPAY_PUBLIC_KEY, "UTF-8")) {//验签失败
//				throw new AlipayApiException("签名失败.....");
//			}

            if (YYStrKits.isBlank(bizContent)) {
                throw new AlipayApiException("支付宝请求信息为空，请求失败.....");
            }

            // 5. 获取业务类型
            String businessType = json.getStr("MsgType");
            if (YYStrKits.isBlank(businessType)) {
                throw new AlipayApiException("支付宝业务类型为空，请求失败.....");
            }

            if ("text".equals(businessType)) {// 接收用户文本消息

                YYLogKits.info(ZFBController.class, "├处理文件消息，消息内容");

            } else if ("event".equals(businessType)) {// 接收支付宝事件事件消息。例如关注、取消关注、进入服务窗
                // 获取事件类型
                String eventType = json.getStr("EventType");
                if (YYStrKits.isBlank(eventType)) {
                    throw new AlipayApiException("支付宝事件类型为空，请求失败.....");
                }

                if ("alipay.service.check".equals(eventType)) {//支付宝网关验证服务

                    YYLogKits.info(ZFBController.class, "├处理事件消息，消息类型：开发者网关验证");

                } else if ("alipay.mobile.public.message.notify".equals(eventType)) {// 消息通知服务

                    YYLogKits.info(ZFBController.class, "├处理事件消息，消息类型：消息通知");

                } else if ("verifygw".equals(eventType)) {//应用网关验证

                    YYLogKits.info(ZFBController.class, "├处理事件消息，消息类型：应用网关验证");
                    responseMsg = iZFBVerifygwService.verifygw();
                    YYLogKits.info(ZFBController.class, "├验证内容：{}", responseMsg);

                } else if ("follow".equals(eventType)) { //用户关注事件

                    YYLogKits.info(ZFBController.class, "├处理事件消息，消息类型：用户关注");
                    responseMsg = iZFBFollowService.floow(json);

                } else if ("unfollow".equals(eventType)) { //用户取消关注事件

                    YYLogKits.info(ZFBController.class, "├处理事件消息，消息类型：用户取消关注");
                    responseMsg = iZFBFollowService.unfloow(json);

                } else if ("enter".equals(eventType)) { //用户进入支付宝生活号事件

                    YYLogKits.info(ZFBController.class, "├处理事件消息，消息类型：用户进入生活号");
                    responseMsg = iZFBEnterService.enter(json);

                }
            } else if ("click".equals(businessType)) {//用户点击菜单事件

                YYLogKits.info(ZFBController.class, "├处理事件消息，用户点击菜单事件.....");
                String ActionParam = json.getStr("ActionParam");
                YYLogKits.info(ZFBController.class, "├菜单关键字{}", ActionParam);
                responseMsg = ActionParam;

            }

            responseMsg = AlipaySignature.encryptAndSign(responseMsg, AlipayConstants.ALIPAY_PUBLIC_KEY, AlipayConstants.PRIVATE_KEY, AlipayConstants.CHARSET, false, true);
            YYLogKits.info(ZFBController.class, "├返回支付宝消息{}", responseMsg);
            response.reset();
            response.setContentType("text/xml;charset=UTF-8");
            PrintWriter writer = response.getWriter();
            writer.write(responseMsg);
            response.flushBuffer();

        } catch (IOException e) {
            YYLogKits.error(ZFBController.class, "├response.flushBuffer()异常,{}", e.getMessage());
        } catch (AlipayApiException e) {
            YYLogKits.error(ZFBController.class, "├支付宝异常,{}", e.getMessage());
        }

        YYLogKits.info(ZFBController.class, "├流程处理结束....");
        YYLogKits.info(ZFBController.class, "└───────────────────────────────────────────────────────────────────────────┘");
    }

    /**
     * <p>
     * 支付宝授权回调地址
     * </p>
     *
     * @author 杨阳
     * @since 2017年9月28日
     */
    @RequestMapping(value = "/callback", method = RequestMethod.POST)
    @ApiOperation(value = "支付宝授权回调地址", httpMethod = "POST")
    public void callBack(HttpServletRequest request) {
        YYLogKits.info(ZFBController.class, "┌───────────────────────────────────────────────────────────────────────────┐");
        YYLogKits.info(ZFBController.class, "├请求支付宝授权回调地址,{}", request.getRequestURI());
        YYLogKits.info(ZFBController.class, "└───────────────────────────────────────────────────────────────────────────┘");
    }
}
